using System;
using System.Collections.Generic;
using Oracle.ManagedDataAccess.Client;
using Oracle.ManagedDataAccess.Types;
using OracleInternal.I18N;

namespace OracleInternal.Sharding
{
	internal class DotnetToDotnetConverter
	{
		private class Key
		{
			private Type source;

			private Type target;

			private int hash;

			public Key(Type s, Type t)
			{
				source = s;
				target = t;
				int hashCode = t.GetHashCode();
				int num = (hashCode >> 1) | (hashCode << 31);
				hash = s.GetHashCode() ^ num;
			}

			public override int GetHashCode()
			{
				return hash;
			}

			public override bool Equals(object rhs)
			{
				Key key = (Key)rhs;
				if (hash == key.hash && source == key.source)
				{
					return target == key.target;
				}
				return false;
			}

			public bool satisfies(Key that)
			{
				if (that.source.Equals(source) || that.source.IsSubclassOf(source))
				{
					if (!target.Equals(that.target))
					{
						return target.IsSubclassOf(that.target);
					}
					return true;
				}
				return false;
			}

			public string toString()
			{
				return "[" + source.Name + " to " + target.Name + "]";
			}
		}

		private delegate byte[] ConvertDel(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra);

		private static Dictionary<Key, ConvertDel> CONVERTERS;

		public static byte[] convert(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
		{
			try
			{
				if (src == null)
				{
					return null;
				}
				Key key = new Key(src.GetType(), target);
				ConvertDel convertDel = CONVERTERS[key];
				if (convertDel != null)
				{
					return convertDel(src, target, conn, srcExtra, targetExtra);
				}
			}
			catch (KeyNotFoundException)
			{
				throw new ArgumentException(OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.SHARDING_INVALID_KEY_VALUE));
			}
			return null;
		}

		static DotnetToDotnetConverter()
		{
			CONVERTERS = new Dictionary<Key, ConvertDel>();
			CONVERTERS.Add(new Key(typeof(byte), typeof(OracleDecimal)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData13 = new OracleDecimal((byte)src).BinData;
				int num9 = binData13[0];
				byte[] array13 = new byte[num9];
				Array.Copy(binData13, 1, array13, 0, num9);
				return array13;
			});
			CONVERTERS.Add(new Key(typeof(byte[]), typeof(OracleDecimal)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData12 = new OracleDecimal(src as byte[], bContainsLength: false).BinData;
				int num8 = binData12[0];
				byte[] array12 = new byte[num8];
				Array.Copy(binData12, 1, array12, 0, num8);
				return array12;
			});
			CONVERTERS.Add(new Key(typeof(byte[]), typeof(OracleDate)), (object src, Type target, OracleConnection conn, object srcExtra, object targetExtra) => new OracleDate(src as byte[]).BinData);
			CONVERTERS.Add(new Key(typeof(byte[]), typeof(OracleBinary)), (object src, Type target, OracleConnection conn, object srcExtra, object targetExtra) => new OracleBinary(src as byte[]).Value);
			CONVERTERS.Add(new Key(typeof(byte[]), typeof(OracleString)), (object src, Type target, OracleConnection conn, object srcExtra, object targetExtra) => src as byte[]);
			CONVERTERS.Add(new Key(typeof(byte[]), typeof(OracleTimeStamp)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData11 = new OracleTimeStamp(src as byte[]).BinData;
				if (binData11 != null && binData11.Length == 11 && binData11[7] == 0 && binData11[8] == 0 && binData11[9] == 0 && binData11[10] == 0)
				{
					byte[] array11 = new byte[7];
					Array.Copy(binData11, array11, 7);
					return array11;
				}
				return binData11;
			});
			CONVERTERS.Add(new Key(typeof(DateTime), typeof(OracleDate)), (object src, Type target, OracleConnection conn, object srcExtra, object targetExtra) => new OracleDate((DateTime)src).BinData);
			CONVERTERS.Add(new Key(typeof(DateTime), typeof(OracleTimeStamp)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData10 = new OracleTimeStamp((DateTime)src).BinData;
				if (binData10 != null && binData10.Length == 11 && binData10[7] == 0 && binData10[8] == 0 && binData10[9] == 0 && binData10[10] == 0)
				{
					byte[] array10 = new byte[7];
					Array.Copy(binData10, array10, 7);
					return array10;
				}
				return binData10;
			});
			CONVERTERS.Add(new Key(typeof(decimal), typeof(OracleDecimal)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData9 = new OracleDecimal((decimal)src).BinData;
				int num7 = binData9[0];
				byte[] array9 = new byte[num7];
				Array.Copy(binData9, 1, array9, 0, num7);
				return array9;
			});
			CONVERTERS.Add(new Key(typeof(double), typeof(OracleDecimal)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData8 = new OracleDecimal((double)src).BinData;
				int num6 = binData8[0];
				byte[] array8 = new byte[num6];
				Array.Copy(binData8, 1, array8, 0, num6);
				return array8;
			});
			CONVERTERS.Add(new Key(typeof(float), typeof(OracleDecimal)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData7 = new OracleDecimal((float)src).BinData;
				int num5 = binData7[0];
				byte[] array7 = new byte[num5];
				Array.Copy(binData7, 1, array7, 0, num5);
				return array7;
			});
			CONVERTERS.Add(new Key(typeof(int), typeof(OracleDecimal)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData6 = new OracleDecimal((int)src).BinData;
				int num4 = binData6[0];
				byte[] array6 = new byte[num4];
				Array.Copy(binData6, 1, array6, 0, num4);
				return array6;
			});
			CONVERTERS.Add(new Key(typeof(long), typeof(OracleDecimal)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData5 = new OracleDecimal((long)src).BinData;
				int num3 = binData5[0];
				byte[] array5 = new byte[num3];
				Array.Copy(binData5, 1, array5, 0, num3);
				return array5;
			});
			CONVERTERS.Add(new Key(typeof(OracleBinary), typeof(OracleBinary)), (object src, Type target, OracleConnection conn, object srcExtra, object targetExtra) => ((OracleBinary)src).Value);
			CONVERTERS.Add(new Key(typeof(OracleDate), typeof(OracleDate)), (object src, Type target, OracleConnection conn, object srcExtra, object targetExtra) => ((OracleDate)src).BinData);
			CONVERTERS.Add(new Key(typeof(OracleDecimal), typeof(OracleDecimal)), (object src, Type target, OracleConnection conn, object srcExtra, object targetExtra) => ((OracleDecimal)src).BinData);
			CONVERTERS.Add(new Key(typeof(OracleString), typeof(OracleString)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				Conv conv2 = targetExtra as Conv;
				if (src == null)
				{
					throw new ArgumentNullException("src", OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.SHARDING_NULL_KEY));
				}
				if (conv2 == null)
				{
					throw new ArgumentNullException("conv");
				}
				string value = ((OracleString)src).Value;
				return conv2.ConvertStringToBytes(value, 0, value.Length);
			});
			CONVERTERS.Add(new Key(typeof(OracleTimeStamp), typeof(OracleTimeStamp)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData4 = ((OracleTimeStamp)src).BinData;
				if (binData4 != null && binData4.Length == 11 && binData4[7] == 0 && binData4[8] == 0 && binData4[9] == 0 && binData4[10] == 0)
				{
					byte[] array4 = new byte[7];
					Array.Copy(binData4, array4, 7);
					return array4;
				}
				return binData4;
			});
			CONVERTERS.Add(new Key(typeof(short), typeof(OracleDecimal)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData3 = new OracleDecimal((short)src).BinData;
				int num2 = binData3[0];
				byte[] array3 = new byte[num2];
				Array.Copy(binData3, 1, array3, 0, num2);
				return array3;
			});
			CONVERTERS.Add(new Key(typeof(string), typeof(OracleDate)), (object src, Type target, OracleConnection conn, object srcExtra, object targetExtra) => new OracleDate(src as string).BinData);
			CONVERTERS.Add(new Key(typeof(string), typeof(OracleDecimal)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData2 = new OracleDecimal(src as string).BinData;
				int num = binData2[0];
				byte[] array2 = new byte[num];
				Array.Copy(binData2, 1, array2, 0, num);
				return array2;
			});
			CONVERTERS.Add(new Key(typeof(string), typeof(OracleString)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				Conv conv = targetExtra as Conv;
				if (src == null)
				{
					throw new ArgumentNullException("src", OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.SHARDING_NULL_KEY));
				}
				if (conv == null)
				{
					throw new ArgumentNullException("conv");
				}
				string text = src as string;
				return conv.ConvertStringToBytes(text, 0, text.Length);
			});
			CONVERTERS.Add(new Key(typeof(string), typeof(OracleTimeStamp)), delegate(object src, Type target, OracleConnection conn, object srcExtra, object targetExtra)
			{
				byte[] binData = new OracleTimeStamp(src as string).BinData;
				if (binData != null && binData.Length == 11 && binData[7] == 0 && binData[8] == 0 && binData[9] == 0 && binData[10] == 0)
				{
					byte[] array = new byte[7];
					Array.Copy(binData, array, 7);
					return array;
				}
				return binData;
			});
		}
	}
}
